package com.edvard.backup;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import cn.kuaipan.android.openapi.AuthActivity;
import cn.kuaipan.android.openapi.AuthSession;
import cn.kuaipan.android.openapi.KuaipanAPI;
import cn.kuaipan.android.openapi.session.AccessTokenPair;
import cn.kuaipan.android.openapi.session.AppKeyPair;
import cn.kuaipan.android.sdk.exception.KscException;
import cn.kuaipan.android.sdk.exception.KscRuntimeException;
import cn.kuaipan.android.sdk.model.KuaipanFile;
import cn.kuaipan.android.sdk.oauth.Session.Root;

import com.edvard.jsbackup.R;
import com.edvard.util.CommonMethodActivity;
import com.edvard.util.DatabaseHelper;
import com.edvard.util.DownloadTask;
import com.edvard.util.MkdirTask;
import com.edvard.util.RequestBase;
import com.edvard.util.UploadTask;

/**
 * 金山备份
 * 
 * @author edvard
 * 
 */
public class JinShanBackupActivity extends CommonMethodActivity implements
		OnClickListener {

	private static final String TAG = "BackupActivity";

	/**
	 * comsemer_key 和 comsumer_serect
	 */
	private static final String APP_KEY = "" + "xc8vGOU1bMxGSdxF";
	private static final String APP_SECRET = "" + "YlrtbYeTLSrZJ8V8";

	/**
	 * 对应的token的键值对
	 */
	final static private String ACCOUNT_PREFS_NAME = "prefs";
	final static private String ACCESS_KEY_NAME = "ACCESS_KEY";
	final static private String ACCESS_SECRET_NAME = "ACCESS_SECRET";
	final static private String ACCESS_AUTH_TYPE_NAME = "ACCESS_AUTH_TYPE_NAME";
	final static private String ACCESS_UID_NAME = "ACCESS_UID_NAME";

	/**
	 * 远程保存的文件夹和路径
	 */
	final static public String SAVE_FOLDER = "/财务管理数据备份";
	final static private String REMOTE_FOLDER = "/财务管理数据备份/FinanceDB.db";
	final static private int BACKUP_FILE_EXIST = 22;

	/**
	 * 快盘sdk对应的api变量
	 */
	KuaipanAPI mApi;
	private AuthSession mAuthSession;
	private ArrayList<KuaipanFile> mFileDataList;
	private int authType;
	private boolean mLoggedIn;

	/**
	 * 处理的线程对象
	 */
	Handler handlerRecover;

	/**
	 * 控件变量
	 */
	Button btnBack;
	TextView tvLogin, tvBackup, tvRecover, tvLogout;
	LinearLayout llLogin, llSync, llLogout;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mAuthSession = buildSession();
		mApi = new KuaipanAPI(this, mAuthSession);
		setContentView(R.layout.activity_jin_shan_backup);

		findViewById();
		setListener();

		mFileDataList = new ArrayList<KuaipanFile>();
		/**
		 * 根据是否已经授权来更新 界面的UI
		 */
		setLoggedIn(mApi.isAuthorized());
	}

	public void findViewById() {
		btnBack = (Button) findViewById(R.id.btn_backup_back);
		tvBackup = (TextView) findViewById(R.id.tv_backup);
		tvRecover = (TextView) findViewById(R.id.tv_recover);
		tvLogin = (TextView) findViewById(R.id.tv_login);
		tvLogout = (TextView) findViewById(R.id.tv_logout);
		llLogin = (LinearLayout) findViewById(R.id.ll_login);
		llSync = (LinearLayout) findViewById(R.id.ll_sync);
		llLogout = (LinearLayout) findViewById(R.id.ll_logout);
	}

	public void setListener() {
		btnBack.setOnClickListener(this);
		tvBackup.setOnClickListener(this);
		tvRecover.setOnClickListener(this);
		tvLogin.setOnClickListener(this);
		tvLogout.setOnClickListener(this);
	}

	/**
	 * 点击事件
	 */
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub

		if (v == btnBack)
			JinShanBackupActivity.this.finish();
		
		//跳转到登录并授权界面
		if (v == tvLogin)
			mApi.startAuthForResult();

		if (v == tvLogout)
			logOut();

		if (v == tvBackup && mLoggedIn) {
			/**
			 * 创建文件夹并上传数据库文件 在MkdirTask调用了UploadTask进行备份
			 */
			showAlertDialog("确定备份", "确定", "取消",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							// TODO Auto-generated method stub
							/**
							 * 创建上层目录
							 */
							mkdir(SAVE_FOLDER);
							/**
							 * 上传数据库文件
							 */
							uploadDBFile();
						}
					}, null);
		}

		/**
		 * 判断数据库文件是否存在 删除当前数据库 将数据库放在指定文件夹内
		 */
		if (v == tvRecover && mLoggedIn) {
			/**
			 * 检查云端是否存在备份过的数据库文件
			 */
			showAlertDialog("确定还原", "确定", "取消",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							// TODO Auto-generated method stub
							getFileMetadata(REMOTE_FOLDER);
						}
					}, null);

			handlerRecover = new Handler() {
				public void handleMessage(android.os.Message msg) {
					if (msg.what == BACKUP_FILE_EXIST) {
						/**
						 * 如果存在则下载覆盖本地数据库文件
						 */
						downloadDBFile();
					}
				};
			};
		}
	}

	/**
	 * 第一次进行备份的时候将会调用此函数创建文件夹
	 * 
	 * @param path
	 *            在金山网盘创建文件夹的路径
	 */
	public void mkdir(String path) {
		if (TextUtils.isEmpty(path)) {
			return;
		}
		RequestBase request = new RequestBase();
		request.setApi(mApi);
		request.setRemotePath(path);
		new MkdirTask(this).start(request);
	}

	/**
	 * 上传数据库文件
	 */
	public void uploadDBFile() {
		//得到数据库文件路径
		File dbFile = JinShanBackupActivity.this
				.getDatabasePath(DatabaseHelper.DATABASE_NAME);
		//封装请求元
		RequestBase request = new RequestBase();
		//设置请求元属性
		request.setApi(mApi);
		//本地数据库路径
		request.setFilePath(dbFile.getAbsolutePath());
		//云盘储存路径
		request.setRemotePath(JinShanBackupActivity.SAVE_FOLDER);
		//执行异步任务
		new UploadTask(JinShanBackupActivity.this).start(request);
	}

	/**
	 * 下载数据库文件
	 */
	public void downloadDBFile() {
		File dbFile = JinShanBackupActivity.this
				.getDatabasePath(DatabaseHelper.DATABASE_NAME);
		//删除本地数据库文件
		if (dbFile.exists())
			dbFile.delete();
		//下载云端数据库文件
		RequestBase request = new RequestBase();
		request.setApi(mApi);
		request.setFilePath(dbFile.getAbsolutePath());
		request.setRemotePath(REMOTE_FOLDER);
		//下载的异步任务
		new DownloadTask(JinShanBackupActivity.this).start(request);
	}

	/**
	 * 得到当前用户网盘上的文件
	 * 以此来判断是否存在备份数据库文件
	 * @param path
	 */
	void getFileMetadata(String path) {
		if (!mApi.isAuthorized()) {
			showToast("Has not been authorized");
			return;
		}

		new AsyncTask<String, Void, String>() {

			@Override
			protected String doInBackground(String... params) {
				try {
					String filepath = params[0];
					KuaipanFile file = mApi.metadata(filepath);
					mFileDataList.clear();
					/**
					 * 得到path路径下的所有文件夹
					 */
					getAllFiles(mFileDataList, file);
					
					Log.v(TAG, "metadata:" + file.toString());
					return file.toString();
				} catch (KscRuntimeException e) {
					e.printStackTrace();
					Log.v(TAG,
							"KscRuntimeException--Failed!!!" + e.getErrorCode());
				} catch (KscException e) {
					e.printStackTrace();
					Log.v(TAG, "KscException--Failed!!!" + e.getErrorCode());
				} catch (InterruptedException e) {
					e.printStackTrace();
					Log.v(TAG, "InterruptedException--Failed!!!");
				}
				return "";
			}

			@Override
			protected void onPostExecute(String result) {
				super.onPostExecute(result);

				if (TextUtils.isEmpty(result)) {
					showToast("您还没有备份，数据库文件不存在");
					return;
				}
				/**
				 * 当发现云端的文件数量大于1的时候
				 * 将会通知后者下载数据库文件
				 */
				if (mFileDataList.size() == 1)
					handlerRecover.sendEmptyMessage(BACKUP_FILE_EXIST);
			}

		}.execute(new String(path));
	}
	
	/**
	 * 得到当前路径下的所有文件
	 * @param list
	 * @param file
	 */
	public void getAllFiles(ArrayList<KuaipanFile> list, KuaipanFile file) {
		list.add(file);
		if (file.isDirectory()) {
			List<KuaipanFile> childrens = file.getChildren();
			if (childrens != null) {
				int size = childrens.size();
				for (int i = 0; i < size; i++) {
					KuaipanFile children = childrens.get(i);
					if (children.isDirectory()) {
						getAllFiles(list, childrens.get(i));
					} else {
						list.add(children);
					}
				}
			}
		}
	}

	/**
	 * 重建会话
	 * 
	 * @return
	 */
	private AuthSession buildSession() {
		AppKeyPair appKeyPair = new AppKeyPair(APP_KEY, APP_SECRET);
		AuthSession session;

		String[] stored = getKeys();
		if (stored != null) {
			AccessTokenPair accessToken = new AccessTokenPair(stored[0],
					stored[1]);
			if (TextUtils.isEmpty(stored[2])) {

			}
			authType = !TextUtils.isEmpty(stored[2]) ? Integer
					.valueOf(stored[2]) : 0;
			session = new AuthSession(appKeyPair, accessToken, Root.KUAIPAN);
			this.authType = Integer.valueOf(stored[3]);
		} else {
			session = new AuthSession(appKeyPair, Root.KUAIPAN);
		}

		return session;
	}

	/**
	 * 改变ui状态
	 */
	private void setLoggedIn(boolean loggedIn) {
		mLoggedIn = loggedIn;
		if (!loggedIn) {
			showToast("未授权");
			clearDisplay();
		} else {
			llLogin.setVisibility(View.GONE);
			llSync.setVisibility(View.VISIBLE);
			llLogout.setVisibility(View.VISIBLE);
		}
	}

	/**
	 * 当未登录的时候隐藏退出登录的布局
	 */
	private void clearDisplay() {
		// TODO Auto-generated method stub
		llLogin.setVisibility(View.VISIBLE);
		llSync.setVisibility(View.GONE);
		llLogout.setVisibility(View.GONE);
	}

	/**
	 * 
	 * @param title
	 *            标题
	 * @param strPositive
	 *            确定按钮显示的字符串
	 * @param strNegetive
	 *            取消按钮显示的字符串
	 * @param posit
	 *            确定按钮的点击事件
	 * @param neget
	 *            取消按钮的点击事件
	 */
	public void showAlertDialog(String title, String strPositive,
			String strNegetive, DialogInterface.OnClickListener posit,
			DialogInterface.OnClickListener neget) {
		Builder b = new AlertDialog.Builder(this);
		b.setTitle(title);
		b.setPositiveButton(strPositive, posit);
		b.setNegativeButton(strNegetive, neget);
		b.create().show();
	}

	/**
	 * 得到储存在sharedpreferences中的access_token 如果不存在则返回空
	 * 
	 * @return
	 */
	private String[] getKeys() {
		SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
		String key = prefs.getString(ACCESS_KEY_NAME, null);
		String secret = prefs.getString(ACCESS_SECRET_NAME, null);
		String uid = prefs.getString(ACCESS_UID_NAME, null);
		String authType = prefs.getString(ACCESS_AUTH_TYPE_NAME, null);
		if (key != null && secret != null) {
			String[] ret = new String[4];
			ret[0] = key;
			ret[1] = secret;
			ret[2] = uid;
			ret[3] = authType;
			return ret;
		} else {
			return null;
		}
	}

	/**
	 * 储存access_token
	 * 
	 * @param key
	 * @param secret
	 * @param uid
	 * @param authType
	 */
	private void storeKeys(String key, String secret, String uid,
			String authType) {
		// Save the access key for later
		SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
		Editor edit = prefs.edit();
		edit.putString(ACCESS_KEY_NAME, key);
		edit.putString(ACCESS_SECRET_NAME, secret);
		edit.putString(ACCESS_UID_NAME, uid);
		edit.putString(ACCESS_AUTH_TYPE_NAME, authType);
		edit.commit();
	}

	/**
	 * 得到授权结果
	 * 
	 * @param resultCode
	 * @return
	 */
	private String getAuthResultName(int resultCode) {
		if (authType == AuthActivity.CANCELED) {
			return "[CANCELED]";
		} else if (authType == AuthActivity.FAILED) {
			return "[FAILED]";
		} else if (authType == AuthActivity.SUCCESSED) {
			return "[SUCCESSED]";
		}
		return "[UnKnown]";
	}

	/**
	 * 得到授权的方式
	 * 
	 * @param authType
	 * @return
	 */
	private String getAuthName(int authType) {
		if (authType == AuthActivity.WEIBO_AUTH) {
			return "[weibo]";
		} else if (authType == AuthActivity.QQ_AUTH) {
			return "[qq]";
		} else if (authType == AuthActivity.XIAOMI_AUTH) {
			return "[xiaomi]";
		} else if (authType == AuthActivity.KUAIPAN_AUTH) {
			return "[kuaipan]";
		}
		return "[UnKnown]";
	}

	/**
	 * 退出当前用户
	 */
	private void logOut() {
		// Remove credentials from the session
		// mAuthSession.unAuthorize();
		mApi.unAuthorize();
		// Clear our stored keys
		clearKeys();
		// Change UI state to display logged out version
		setLoggedIn(false);
	}

	/**
	 * 清除保存的token
	 */
	private void clearKeys() {
		SharedPreferences prefs = getSharedPreferences(ACCOUNT_PREFS_NAME, 0);
		Editor edit = prefs.edit();
		edit.clear();
		edit.commit();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode,
			Intent intent) {

		Log.v(TAG, "requestCode:" + requestCode + " resultCode:" + resultCode);

		if (requestCode == AuthActivity.AUTH_REQUEST_CODE) {

			Log.v(TAG, "resultCode: " + getAuthResultName(resultCode));
			Log.v(TAG, "ResultData:  " + intent);

			if (intent == null) {
				return;
			}

			if (resultCode == AuthActivity.SUCCESSED && intent != null) {
				
				//得到信息
				Bundle values = intent.getExtras();
				//返回的accessToken
				final String accessToken = values
						.getString(AuthActivity.EXTRA_ACCESS_TOKEN);
				//返回的accessSecert
				final String accessSecret = values
						.getString(AuthActivity.EXTRA_ACCESS_SECRET);
				final String uid = values.getString(AuthActivity.EXTRA_UID);
				
				authType = values.getInt(AuthActivity.EXTRA_AUTH_TYPE);

				Log.v(TAG, "Authorized by " + getAuthName(authType) + " server");

				final String error_code = values
						.getString(AuthActivity.EXTRA_ERROR_CODE);
				Log.v(TAG, "!!!accessToken=" + accessToken + "\n"
						+ "accessSecret=" + accessSecret + "\n" + "uid=" + uid
						+ "\n" + "error_code" + error_code);

				/**
				 * 设置合法的Token键值对，随后isAuthorized将会返回true值
				 */
				mApi.setAccessToken(accessToken, accessSecret);

				setLoggedIn(mApi.isAuthorized());

				// 保存返回的Token
				storeKeys(accessToken, accessSecret, uid,
						String.valueOf(authType));
			}
		}
	}
}
